/**
 * @Copyright 2012, Founder Mobile Media Technology（Chongqing） Co., Ltd L.P. All
 *            rights reserved. The information contained herein is confidential
 *            and proprietary to Founder Mobile Media Technology（Chongqing） Co.,
 *            Ltd, and considered a trade secret as defined under civil and
 *            criminal statutes. Founder Mobile Media Technology（Chongqing） Co.,
 *            Ltd shall pursue its civil and criminal remedies in the event of
 *            unauthorized use or misappropriation of its trade secrets. Use of
 *            this information by anyone other than authorized employees of
 *            Founder Mobile Media Technology（Chongqing） Co., Ltd is granted
 *            only under a written non-disclosure agreement, expressly
 *            prescribing the scope and manner of such use.
 */
package com.g2room.quartz;

import java.util.Date;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

/**
 * 
 * 
 * @createTime: May 9, 2013 11:02:10 AM
 * @author: <a href="mailto:gaoxg@FOUNDER.COM.CN">Xuguo Gao</a>
 * @version: 0.1
 * @lastVersion: 0.1
 * @updateTime:
 * @updateAuthor: <a href="mailto:gaoxg@FOUNDER.COM.CN">Xuguo Gao</a>
 * @changesSum:
 * 
 */
public class SimpleExample {
	public static void main(String[] args) {
		try {
			testJob();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 使用quartz实现的调度任务
	 *
	 * @throws SchedulerException
	 * @throws InterruptedException
	 * @auther <a href="mailto:gaoxg@FOUNDER.COM.CN">Gao Xuguo</a>
	 * May 9, 2013 4:43:01 PM
	 */
	public static void testJob() throws SchedulerException,InterruptedException {
		SchedulerFactory factory = new StdSchedulerFactory();
		// 从工厂里面拿到一个scheduler实例
		Scheduler scheduler = factory.getScheduler();
		// 计算任务的开始时间，DateBuilder.evenMinuteDate方法是取下一个整数分钟
//		Date runTime = DateBuilder.evenMinuteDate(new Date());
		// 任务的开始时间，nextGivenSecondDate方法表示：
		// 当指定时间（w为null时当前时间）之后，每隔多长时间（例子是13秒）触发一次
		Date runTime = DateBuilder.nextGivenSecondDate(null, 16);
		
		// 简单例子
		// 真正执行的任务并不是Job接口的实例，而是用反射的方式实例化的一个Jobs实例
//		JobDetail job = JobBuilder.newJob(Jobs.class).withIdentity("job1", "testGroup").build();
//		// 定义一个触发器，startAt方法定义了任务应当开始的时间
//		Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1",
//				"testGroup").startAt(runTime).build();
//		// 将任务和Trigger放入scheduler
//		scheduler.scheduleJob(job, trigger);

		// 将同一个Job实现作为另外一个任务注册到scheduler，注意名字要区分
//		job = JobBuilder.newJob(Jobs.class).withIdentity("job2", "testGroup").build();
//		trigger = TriggerBuilder.newTrigger().withIdentity("trigger2", 
//				"testGroup").startAt(runTime).build();
//		scheduler.scheduleJob(job, trigger);

//		// @NOTICE
//		// 重复执行,job3表示第一次执行完之后，每隔3秒钟执行一次，重复5次，
		// withRepeatCount参数不包括第一次执行那次，即job3总共执行6次
		// SimpleScheduleBuilder：	重复执行，需要在Trigger的设置里面加入，
		// 							设置重复次数和重复时间即可。
		// repeatForever()方法永远表示一直重复执行，相应的可以设置按小时、分钟、秒一直执行。
		JobDetail job = JobBuilder.newJob(Jobs.class).withIdentity("job3", "testGroup").build();
		job.getJobDataMap().put(Jobs.JOB_DATA_MAP_KEY, 10);
//		Trigger trigger = TriggerBuilder.newTrigger()
//				.withIdentity("trigger3", "testGroup").withSchedule(
//						SimpleScheduleBuilder.simpleSchedule().withRepeatCount(4)
//						.withIntervalInSeconds(2))
//				.startAt(runTime).build();
//		/**
//		 	// 无trigger注册，表示任务立即执行。
//			scheduler.addJob(job, true);
//			// 在scheduler.start之后调用，可以在job开始后重新定义trigger，然后重新注册。
// 			scheduler.rescheduleJob(trigger.getKey(), trigger);
// 			// 可以在shutdown后取出执行的任务数量，一些基本信息封装在SchedulerMetaData对象中。 
//			scheduler.getMetaData().getNumberOfJobsExecuted(); 
//		 */
//		scheduler.scheduleJob(job, trigger);
		/**
			与SimpleTrigger对比：类不同了，现在的是Trigger的子类CronTrigger；
			withSchedule中的参数变为CronScheduleBuilder了  
		    CronScheduleBuilder可以通过类似"0/13 * * * * ?"这种表达式来创建定时任务  
		    当前这个表达式的定义是每个秒是13的倍数，或者是0的时候，都触发任务
 		*/
	  	CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(
				"trigger3", "testGroup").withSchedule(
				CronScheduleBuilder.cronSchedule("0/13 * * * * ?")).build();
	  	/**
	  	--------------------------------------
	  	   秒 分 时  日 月 周 年
	  	   0 0  12  *  * ?         每天12点触发
	  	   0 15 10 ? * *           每天10点15分触发
	  	   0 15 10 * * ?           每天10点15分触发
	  	   0 15 10 * * ? *         每天10点15分触发
	  	   0 15 10 * * ? 2005      2005年每天10点15分触发
	  	   0 * 14 * * ?            每天下午的 2点到2点59分每分触发
	  	   0 0/5 14 * * ?          每天下午的 2点到2点59分(整点开始，每隔5分触发)
	  	   0 0/5 14,18 * * ?       每天下午的 2点到2点59分(整点开始，每隔5分触发) 每天下午的 18点到18点59分(整点开始，每隔5分触发)
	  	   0 0-5 14 * * ?          每天下午的 2点到2点05分每分触发
	  	   0 10,44 14 ? 3 WED      3月分每周三下午的 2点10分和2点44分触发
	  	   0 15 10 ? * MON-FRI     从周一到周五每天上午的10点15分触发
	  	   0 15 10 15 * ?          每月15号上午10点15分触发
	  	   0 15 10 L * ?           每月最后一天的10点15分触发
	  	   0 15 10 ? * 6L          每月最后一周的星期五的10点15分触发
	  	   0 15 10 ? * 6L 2002-2005    从2002年到2005年每月最后一周的星期五的10点15分触发
	  	   0 15 10 ? * 6#3         每月的第三周的星期五开始触发
	  	   0 0 12 1/5 * ?          每月的第一个中午开始每隔5天触发一次
	  	   0 11 11 11 11 ?         每年的11月11号 11点11分触发(光棍节)
	  	--------------------------------------
	  	其次，通配符，主要的有星号(*)；问号(?)；减号(-)；逗号(,)；斜杠(/)；L字母；W字母；井号(#). 
		星号：表示任意时刻
		问号：只能在日或周字段上使用，http://blog.csdn.net/chh_jiang/article/details/4603529 这里有比较清晰的解释，简单的理解就是日期和星期是有冲突的，指定其中一个的话，另外一个是没办法指定的，比如每个月12号和每个星期二，这两个是"互斥"的，不能用日期和周来指定所有“每个是星期二的12号”这个时间。
		减号：范围，如 1-5秒
		逗号：列表，如 1,5,10 秒
		斜杠：等步长序列，如3/13秒 表示 3,16,29,42,55,3,16...
		L：仅在日和周上支持，表示允许的最后一个值，注意不要让范围和列表与L连用
		W：工作日
		井号：为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中，表示把任务安排在当月的第二个星期一。
		井号和L W用的比较少，其实简单实用的话，根据那些注释中的去改就够了~~
	  	*/
	  	scheduler.scheduleJob(job, cronTrigger);
		// 开始调度
		scheduler.start();
		try {
//			// 等待65秒，保证下一个整数分钟出现，这里注意，如果主线程停止，任务是不会执行的
//			Thread.sleep(5L * 1000L);
			Thread.sleep(2000L * 1000L);
		} catch (Exception e) {
		}
		// scheduler结束
		scheduler.shutdown(true);
		System.out.println("==============" + scheduler.getMetaData().getNumberOfJobsExecuted());
	}
}
